import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { Select, Spin, TreeSelect } from 'antd';
import { debounce } from 'lodash-es';

// 组件 Props 类型定义
interface RemoteSelectProps {
  // 基础属性
  value?: any;
  onChange?: (value: any, option?: any) => void;
  onSelect?: (value: any, option?: any) => void;
  placeholder?: string;
  disabled?: boolean;
  allowClear?: boolean;
  searchParams?: Record<string, any>;

  // 选择模式
  mode?: 'single' | 'multiple';

  // 组件类型
  type?: 'select' | 'treeSelect';

  // 远程请求相关
  fetchData: (params: FetchParams) => Promise<FetchResponse>;
  transformData?: (data: any[]) => OptionItem[];

  // 搜索和分页
  searchable?: boolean;
  pageSize?: number;
  debounceWait?: number;

  // 样式
  style?: React.CSSProperties;
  className?: string;

  // TreeSelect 特有属性
  treeCheckable?: boolean;
  treeDefaultExpandAll?: boolean;
  treeNodeFilterProp?: string;
}

// 请求参数类型
export interface FetchParams {
  keyword?: string;
  page: number;
  pageSize: number;
  [propName: string]: unknown;
}

// 请求响应类型
interface FetchResponse {
  data: unknown[];
  total: number;
  hasMore?: boolean;
}

// 选项数据类型
interface OptionItem {
  label: string;
  value: any;
  disabled?: boolean;
  children?: OptionItem[];
  // TreeSelect 特有
  title?: string;
  key?: string;
}

const RemoteSelect: React.FC<RemoteSelectProps> = ({
  value,
  onChange,
  onSelect,
  placeholder = '请选择',
  disabled = false,
  allowClear = true,
  mode = 'single',
  type = 'select',
  fetchData,
  transformData,
  searchable = false,
  pageSize = 30,
  debounceWait = 300,
  style,
  className,
  treeCheckable = false,
  treeDefaultExpandAll = false,
  treeNodeFilterProp = 'title',
  searchParams = {},
}) => {
  // 状态管理
  const [options, setOptions] = useState<OptionItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [searchValue, setSearchValue] = useState('');
  const [currentPage, setCurrentPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);
  const [total, setTotal] = useState(0);
  const [oldSearchParams, setOldSearchParams] = useState<Record<string, any>>();

  // refs
  const selectRef = useRef<any>(null);
  const fetchingRef = useRef(false);

  // 默认数据转换函数
  const defaultTransformData = useCallback((data: any[]): OptionItem[] => {
    return data.map(item => ({
      label: item.label ?? item.name ?? item.title ?? String(item.value),
      value: String(item.value ?? item.id),
      disabled: item.disabled ?? false,
      children: item.children ? defaultTransformData(item.children) : undefined,
      // TreeSelect 特有属性
      title: item.title ?? item.label ?? item.name ?? String(item.value),
      key: String(item.value ?? item.id),
      data: item,
    }));
  }, []);

  // 获取数据
  const loadData = useCallback(
    async (keyword: string = '', page: number = 1, append: boolean = false) => {
      if (fetchingRef.current) return;

      fetchingRef.current = true;
      setLoading(true);
      try {
        const response = await fetchData({
          ...searchParams,
          keyword,
          page,
          pageSize,
        });

        const transformedData = transformData
          ? transformData(response.data)
          : defaultTransformData(response.data);

        setOptions(prev => (append ? [...prev, ...transformedData] : transformedData));
        setTotal(response.total);
        setHasMore(response.hasMore ?? response.data.length === pageSize);
        setCurrentPage(page);
      } catch (error) {
        console.error('Failed to fetch data:', error);
      } finally {
        setLoading(false);
        fetchingRef.current = false;
      }
    },
    [fetchData, transformData, defaultTransformData, pageSize, searchParams]
  );

  // 防抖搜索
  const debouncedSearch = useMemo(
    () =>
      debounce((keyword: string) => {
        setSearchValue(keyword);
        setCurrentPage(1);
        loadData(keyword, 1, false);
      }, debounceWait),
    [loadData, debounceWait]
  );

  // 初始化加载数据
  useEffect(() => {
    if (JSON.stringify(oldSearchParams) !== JSON.stringify(searchParams)) {
      console.log('初始化加载数据', searchParams);
      setOldSearchParams(searchParams);
      loadData();
    }
  }, [searchParams]);

  // 搜索处理
  const handleSearch = useCallback(
    (keyword: string) => {
      if (searchable) {
        debouncedSearch(keyword);
      }
    },
    [searchable, debouncedSearch]
  );

  // 滚动加载更多
  const handlePopupScroll = useCallback(
    (e: React.UIEvent<HTMLDivElement>) => {
      const { target } = e;
      const element = target as HTMLDivElement;

      if (
        element.scrollTop + element.offsetHeight === element.scrollHeight &&
        hasMore &&
        !loading &&
        !fetchingRef.current
      ) {
        loadData(searchValue, currentPage + 1, true);
      }
    },
    [hasMore, loading, searchValue, currentPage, loadData]
  );

  // 值变化处理
  const handleChange = useCallback(
    (val: any, option: any) => {
      onChange?.(val, option);
      onSelect?.(val, option);
    },
    [onChange, onSelect]
  );

  // 清空搜索
  const handleClear = useCallback(() => {
    setSearchValue('');
    setCurrentPage(1);
    loadData('', 1, false);
  }, [loadData]);

  // Select 组件配置
  const selectProps: any = {
    value,
    onChange: handleChange,
    placeholder,
    disabled,
    allowClear,
    style,
    className,
    ref: selectRef,
    loading,
    options,
    showSearch: searchable,
    ...(searchable ? { onSearch: handleSearch } : {}), // 只有在searchable为true时才添加onSearch
    onClear: handleClear,
    onPopupScroll: handlePopupScroll,
    filterOption: false, // 关闭本地过滤，使用远程搜索
    notFoundContent: loading ? <Spin size="small" /> : '暂无数据',
    popupRender: (menu: React.ReactNode) => (
      <div>
        {menu}
        {loading && hasMore && (
          <div style={{ textAlign: 'center', padding: '8px' }}>
            <Spin size="small" />
          </div>
        )}
      </div>
    ),
  };

  // TreeSelect 组件配置
  const treeSelectProps: any = {
    ...selectProps,
    treeData: options,
    treeCheckable: mode === 'multiple' ? treeCheckable : false,
    treeDefaultExpandAll,
    treeNodeFilterProp,
    showCheckedStrategy: TreeSelect.SHOW_PARENT,
  };

  // 根据模式设置选择属性
  if (mode === 'multiple') {
    selectProps.mode = 'multiple';
    if (type === 'treeSelect') {
      treeSelectProps.multiple = true;
    }
  }
  // console.log('treeSelectProps', treeSelectProps);

  // 渲染组件
  if (type === 'treeSelect') {
    return <TreeSelect {...treeSelectProps} />;
  }

  return <Select {...selectProps} />;
};

export default RemoteSelect;

export const RemoteSelectExample: React.FC = () => {
  const [value, setValue] = useState<any>();
  const [multiValue, setMultiValue] = useState<any[]>([]);
  const [treeValue, setTreeValue] = useState<any>();

  // 模拟远程数据获取
  const mockFetchData = async ({
    keyword,
    page,
    pageSize,
  }: FetchParams): Promise<FetchResponse> => {
    // 模拟网络延迟
    await new Promise(resolve => setTimeout(resolve, 500));

    // 模拟数据
    const allData = Array.from({ length: 100 }, (_, i) => ({
      id: i + 1,
      name: `选项 ${i + 1} ${keyword ? `(搜索: ${keyword})` : ''}`,
      value: i + 1,
      disabled: i % 10 === 0, // 每10个有一个禁用
    }));

    // 模拟搜索过滤
    const filteredData = keyword
      ? allData.filter(item => item.name.toLowerCase().includes(keyword.toLowerCase()))
      : allData;

    // 分页
    const start = (page - 1) * pageSize;
    const end = start + pageSize;
    const pageData = filteredData.slice(start, end);

    return {
      data: pageData,
      total: filteredData.length,
      hasMore: end < filteredData.length,
    };
  };

  // 模拟树形数据获取
  const mockFetchTreeData = async ({
    keyword,
    page,
    pageSize,
  }: FetchParams): Promise<FetchResponse> => {
    await new Promise(resolve => setTimeout(resolve, 500));

    const treeData = Array.from({ length: 50 }, (_, i) => ({
      id: i + 1,
      title: `父节点 ${i + 1}`,
      value: `parent-${i + 1}`,
      children: Array.from({ length: 3 }, (__, j) => ({
        id: `${i + 1}-${j + 1}`,
        title: `子节点 ${i + 1}-${j + 1}`,
        value: `child-${i + 1}-${j + 1}`,
      })),
    }));

    const filteredData = keyword
      ? treeData.filter(
          item =>
            item.title.toLowerCase().includes(keyword.toLowerCase()) ||
            item.children.some(child => child.title.toLowerCase().includes(keyword.toLowerCase()))
        )
      : treeData;

    const start = (page - 1) * pageSize;
    const end = start + pageSize;
    const pageData = filteredData.slice(start, end);

    return {
      data: pageData,
      total: filteredData.length,
      hasMore: end < filteredData.length,
    };
  };

  return (
    <div style={{ padding: '24px' }}>
      <h2>RemoteSelect 组件示例</h2>

      <div style={{ marginBottom: '24px' }}>
        <h3>单选 Select</h3>
        <RemoteSelect
          value={value}
          onChange={setValue}
          fetchData={mockFetchData}
          placeholder="请选择单个选项"
          style={{ width: '300px' }}
        />
        <p>选中值: {JSON.stringify(value)}</p>
      </div>

      <div style={{ marginBottom: '24px' }}>
        <h3>多选 Select</h3>
        <RemoteSelect
          mode="multiple"
          value={multiValue}
          onChange={setMultiValue}
          fetchData={mockFetchData}
          placeholder="请选择多个选项"
          style={{ width: '300px' }}
        />
        <p>选中值: {JSON.stringify(multiValue)}</p>
      </div>

      <div style={{ marginBottom: '24px' }}>
        <h3>TreeSelect</h3>
        <RemoteSelect
          type="treeSelect"
          value={treeValue}
          onChange={setTreeValue}
          fetchData={mockFetchTreeData}
          placeholder="请选择树形选项"
          style={{ width: '300px' }}
          treeCheckable={false}
          treeDefaultExpandAll={true}
        />
        <p>选中值: {JSON.stringify(treeValue)}</p>
      </div>
    </div>
  );
};
